<template>
  <div class="h-full overflow-hidden flex flex-col">
    <a-upload-dragger name="file" :show-upload-list="false" :before-upload="beforeUpload" @change="handleChange">
      <p class="ant-upload-drag-icon">
        <inbox-outlined />
      </p>
      <p class="ant-upload-text">点击或拖拽文件到此处上传</p>
      <p class="ant-upload-hint">支持dcm文件等</p>
    </a-upload-dragger>

    <div class="w-full flex flex-1 overflow-hidden">
      <div class="pt-4 h-full w-2/3 flex flex-col overflow-hidden">
        <a-space class="pb-2 flex items-center justify-center">
          <a-button type="primary" :ghost="activeBtn !== 'Opacity'" @click="onClick('Opacity')"> 透明度</a-button>
          <a-button type="primary" :ghost="activeBtn !== 'WindowLevel'" @click="onClick('WindowLevel')"> 对比度</a-button>
          <a-button type="primary" :ghost="activeBtn !== 'ZoomAndPan'" @click="onClick('ZoomAndPan')"> 缩放</a-button>
          <a-dropdown>
            <template #overlay>
              <a-menu @click="handleMenuClick">
                <a-menu-item key="Arrow"> 剪头 </a-menu-item>
                <a-menu-item key="Ruler"> 标尺 </a-menu-item>
                <a-menu-item key="Rectangle"> 矩形 </a-menu-item>
                <a-menu-item key="Circle"> 圆形 </a-menu-item>
                <a-menu-item key="Protractor"> 角度 </a-menu-item>
                <a-menu-item key="Roi"> Roi </a-menu-item>
              </a-menu>
            </template>
            <a-button type="primary" :ghost="activeBtn !== 'Draw'">绘图</a-button>
          </a-dropdown>
        </a-space>
        <div id="dwv-box" class="flex-1 overflow-hidden">
          <div id="dropBox"></div>
        </div>
      </div>
      <div class="pt-4 w-1/3 border-l pl-4 h-full overflow-auto">
        <div v-if="metaData.length === 0">请选择文件</div>
        <a-descriptions v-else title="数据" bordered :column="1" size="small">
          <a-descriptions-item v-for="item in metaData" :key="item.name">
            <template #label>
              <div class="w-40 truncate">{{ item.name }}</div>
            </template>
            {{ item.value }}
          </a-descriptions-item>
        </a-descriptions>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { App, AppOptions, ViewConfig, ToolConfig, getTagFromKey } from 'dwv'
import { InboxOutlined } from '@ant-design/icons-vue'

let dwvApp = null
const metaData = ref([])
const dataLoaded = ref(false)
const activeBtn = ref()
const fileList = ref([])
const beforeUpload = (file) => {
  fileList.value = [...(fileList.value || []), file]

  return false
}
const handleChange = (files) => {
  dwvApp = null
  initDwv()
  dwvApp.loadFiles([files.file])
}

const handleMenuClick = (e) => {
  activeBtn.value = 'Draw'
  dwvApp.setTool('Draw')
  dwvApp.setToolFeatures({ shapeName: e.key })
}
const onClick = (toolName) => {
  activeBtn.value = toolName
  dwvApp.setTool(toolName)
}

const initDwv = () => {
  dwvApp = new App()
  const viewConfig0 = new ViewConfig('dwv-box')
  const viewConfigs = { '*': [viewConfig0] }
  const options = new AppOptions(viewConfigs)
  options['tools'] = {
    Scroll: new ToolConfig(),
    ZoomAndPan: new ToolConfig(),
    WindowLevel: new ToolConfig(),
    Opacity: new ToolConfig(),
    Draw: new ToolConfig(['Arrow', 'Ruler', 'Rectangle', 'Circle', 'Protractor', 'Roi'])
  }
  dwvApp.init(options)
  dwvApp.addEventListener('loadstart', (/*event*/) => {
    // reset flags
    dataLoaded.value = false
  })
  dwvApp.addEventListener('load', (event) => {
    // set dicom tags
    metaData.value = getMetaArray(dwvApp.getMetaData(event.dataid), 1)
    // set data loaded flag
    dataLoaded.value = true
  })
}

const getMetaArray = (tagData, instanceNumber) => {
  let reducer
  if (isDicomMeta(tagData)) {
    reducer = getDicomTagReducer(tagData, instanceNumber, '')
  } else {
    reducer = getTagReducer(tagData)
  }
  const keys = Object.keys(tagData)
  return keys.reduce(reducer, [])
}

const isDicomMeta = (meta) => {
  return typeof meta['00020010'] !== 'undefined'
}

const getTagReducer = (tagData) => {
  return function (accumulator, currentValue) {
    accumulator.push({
      name: currentValue,
      value: tagData[currentValue].value
    })
    return accumulator
  }
}

const getDicomTagReducer = (tagData, instanceNumber, prefix) => {
  return (accumulator, currentValue) => {
    const tag = getTagFromKey(currentValue)
    let key = tag.getNameFromDictionary()
    if (typeof key === 'undefined') {
      // add 'x' to help sorting
      key = 'x' + tag.getKey()
    }
    const name = key
    const element = tagData[currentValue]
    let value = element.value
    // possible 'merged' object
    // (use slice method as test for array and typed array)
    if (typeof value.slice === 'undefined' && typeof value[instanceNumber] !== 'undefined') {
      value = value[instanceNumber]
    }
    // force instance number (otherwise takes value in non indexed array)
    if (name === 'InstanceNumber') {
      value = instanceNumber
    }
    // recurse for sequence
    if (element.vr === 'SQ') {
      // sequence tag
      accumulator.push({
        name: (prefix ? prefix + ' ' : '') + name,
        value: ''
      })
      // sequence value
      for (let i = 0; i < value.length; ++i) {
        const sqItems = value[i]
        const keys = Object.keys(sqItems)
        const res = keys.reduce(getDicomTagReducer(sqItems, instanceNumber, prefix + '[' + i + ']'), [])
        accumulator = accumulator.concat(res)
      }
    } else {
      // shorten long 'o'ther data
      if (element.vr[0] === 'O' && value.length > 10) {
        value = value.slice(0, 10).toString() + '... (len:' + value.length + ')'
      }
      accumulator.push({
        name: (prefix ? prefix + ' ' : '') + name,
        value: value.toString()
      })
    }
    return accumulator
  }
}
// onMounted(() => {})
</script>

<style>
.layer {
  position: absolute;
  pointer-events: none;
}
</style>
